home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Direct3D / HDRCubeMap / HDRCubeMap.cpp next >
Encoding:
C/C++ Source or Header  |  2004-09-28  |  57.7 KB  |  1,347 lines

  1. //--------------------------------------------------------------------------------------
  2. // File: HDRCubeMap.cpp
  3. //
  4. // This sample demonstrates a common shadow technique called shadow mapping.
  5. //
  6. // Copyright (c) Microsoft Corporation. All rights reserved.
  7. //--------------------------------------------------------------------------------------
  8. #include "dxstdafx.h"
  9. #include "resource.h"
  10.  
  11. //#define DEBUG_VS   // Uncomment this line to debug vertex shaders 
  12. //#define DEBUG_PS   // Uncomment this line to debug pixel shaders 
  13.  
  14.  
  15. //--------------------------------------------------------------------------------------
  16. // Defines, and constants
  17. //--------------------------------------------------------------------------------------
  18.  
  19. #define ENVMAPSIZE 256
  20. // Currently, 4 is the only number of lights supported.
  21. #define NUM_LIGHTS 4
  22. #define LIGHTMESH_RADIUS 0.2f
  23. #define HELPTEXTCOLOR D3DXCOLOR( 0.0f, 1.0f, 0.3f, 1.0f )
  24.  
  25.  
  26. D3DVERTEXELEMENT9 g_aVertDecl[] =
  27. {
  28.     { 0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
  29.     { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   0 },
  30.     { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
  31.     D3DDECL_END()
  32. };
  33.  
  34.  
  35. LPCTSTR g_atszMeshFileName[] =
  36. {
  37.     L"misc\\teapot.x",
  38.     L"misc\\skullocc.x",
  39.     L"misc\\car.x"
  40. };
  41.  
  42. #define NUM_MESHES ( sizeof(g_atszMeshFileName) / sizeof(g_atszMeshFileName[0]) )
  43.  
  44. struct ORBITDATA
  45. {
  46.     LPCTSTR     tszXFile;  // X file
  47.     D3DVECTOR   vAxis;     // Axis of rotation
  48.     float       fRadius;   // Orbit radius
  49.     float       fSpeed;    // Orbit speed in radians per second
  50. };
  51.  
  52.  
  53. // Mesh file to use for orbiter objects
  54. // These don't have to use the same mesh file.
  55. ORBITDATA g_OrbitData[] =
  56. {
  57.     {L"airplane\\airplane 2.x", { -1.0f, 0.0f, 0.0f }, 2.0f, D3DX_PI * 1.0f },
  58.     {L"airplane\\airplane 2.x", { 0.3f,  1.0f, 0.3f }, 2.5f, D3DX_PI / 2.0f }
  59. };
  60.  
  61.  
  62. HRESULT ComputeBoundingSphere( CDXUTMesh &Mesh, D3DXVECTOR3 *pvCtr, float *pfRadius )
  63. {
  64.     HRESULT hr;
  65.  
  66.     // Obtain the bounding sphere
  67.     LPD3DXMESH pMeshObj = Mesh.GetSysMemMesh();
  68.     if( !pMeshObj )
  69.         return E_FAIL;
  70.  
  71.     // Obtain the declaration
  72.     D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
  73.     if( FAILED( hr = pMeshObj->GetDeclaration( decl ) ) )
  74.         return hr;
  75.  
  76.     // Lock the vertex buffer
  77.     LPVOID pVB;
  78.     if( FAILED( hr = pMeshObj->LockVertexBuffer( D3DLOCK_READONLY, &pVB ) ) )
  79.         return hr;
  80.  
  81.     // Compute the bounding sphere
  82.     UINT uStride = D3DXGetDeclVertexSize( decl, 0 );
  83.     hr = D3DXComputeBoundingSphere( (const D3DXVECTOR3 *)pVB, pMeshObj->GetNumVertices(),
  84.                                     uStride, pvCtr, pfRadius );
  85.     pMeshObj->UnlockVertexBuffer();
  86.  
  87.     return hr;
  88. }
  89.  
  90.  
  91.  
  92.  
  93. //--------------------------------------------------------------------------------------
  94. // Encapsulate an object in the scene with its world transformation
  95. // matrix.
  96. //--------------------------------------------------------------------------------------
  97. struct CObj
  98. {
  99.     D3DXMATRIXA16 m_mWorld;  // World transformation
  100.     CDXUTMesh     m_Mesh;    // Mesh object
  101.  
  102. public:
  103.     CObj()
  104.         { D3DXMatrixIdentity( &m_mWorld ); }
  105.     ~CObj()
  106.         { }
  107.     HRESULT WorldCenterAndScaleToRadius( float fRadius )
  108.     {
  109.         //
  110.         // Compute the world transformation matrix
  111.         // to center the mesh at origin in world space
  112.         // and scale its size to the specified radius.
  113.         //
  114.         HRESULT hr;
  115.  
  116.         float fRadiusBound;
  117.         D3DXVECTOR3 vCtr;
  118.         if( FAILED( hr = ::ComputeBoundingSphere( m_Mesh, &vCtr, &fRadiusBound ) ) )
  119.             return hr;
  120.  
  121.         D3DXMatrixTranslation( &m_mWorld, -vCtr.x, -vCtr.y, -vCtr.z );
  122.         D3DXMATRIXA16 mScale;
  123.         D3DXMatrixScaling( &mScale, fRadius / fRadiusBound,
  124.                                     fRadius / fRadiusBound,
  125.                                     fRadius / fRadiusBound );
  126.         D3DXMatrixMultiply( &m_mWorld, &m_mWorld, &mScale );
  127.  
  128.         return hr;
  129.     }  // WorldCenterAndScaleToRadius
  130. };
  131.  
  132.  
  133. //--------------------------------------------------------------------------------------
  134. // Encapsulate an orbiter object in the scene with related data
  135. //--------------------------------------------------------------------------------------
  136. class COrbiter : public CObj
  137. {
  138. public:
  139.     D3DXVECTOR3   m_vAxis;       // orbit axis
  140.     float         m_fRadius;     // orbit radius
  141.     float         m_fSpeed;      // Speed, angle in radian per second
  142.  
  143. public:
  144.     COrbiter() : m_vAxis( 0.0f, 1.0f, 0.0f ), m_fRadius(1.0f), m_fSpeed( D3DX_PI )
  145.         { }
  146.     void SetOrbit( D3DXVECTOR3 &vAxis, float fRadius, float fSpeed )
  147.     {
  148.         // Call this after m_mWorld is initialized
  149.         m_vAxis = vAxis; m_fRadius = fRadius; m_fSpeed = fSpeed;
  150.         D3DXVec3Normalize( &m_vAxis, &m_vAxis );
  151.  
  152.         // Translate by m_fRadius in -Y direction
  153.         D3DXMATRIXA16 m;
  154.         D3DXMatrixTranslation( &m, 0.0f, -m_fRadius, 0.0f );
  155.         D3DXMatrixMultiply(&m_mWorld, &m_mWorld, &m );
  156.  
  157.         // Apply rotation from X axis to the orbit axis
  158.         D3DXVECTOR3 vX(1.0f, 0.0f, 0.0f);
  159.         D3DXVECTOR3 vRot;
  160.         D3DXVec3Cross( &vRot, &m_vAxis, &vX );  // Axis of rotation
  161.         // If the cross product is 0, m_vAxis is on the X axis
  162.         // So we either rotate 0 or PI.
  163.         if( D3DXVec3LengthSq( &vRot ) == 0 )
  164.         {
  165.             if( m_vAxis.x < 0.0f )
  166.                 D3DXMatrixRotationY( &m, D3DX_PI ); // PI
  167.             else
  168.                 D3DXMatrixIdentity( &m );           // 0
  169.         } else
  170.         {
  171.             float fAng = (float)acos( D3DXVec3Dot( &m_vAxis, &vX ) );  // Angle to rotate
  172.             // Find out direction to rotate
  173.             D3DXVECTOR3 vXxRot;  // X cross vRot
  174.             D3DXVec3Cross( &vXxRot, &vX, &vRot );
  175.             if( D3DXVec3Dot( &vXxRot, &m_vAxis ) >= 0 )
  176.                 fAng = -fAng;
  177.             D3DXMatrixRotationAxis( &m, &vRot, fAng );
  178.         }
  179.         D3DXMatrixMultiply( &m_mWorld, &m_mWorld, &m );
  180.     }
  181.     void Orbit( float fElapsedTime )
  182.     {
  183.         // Compute the orbit transformation and apply to m_mWorld
  184.         D3DXMATRIXA16 m;
  185.  
  186.         D3DXMatrixRotationAxis( &m, &m_vAxis, m_fSpeed * fElapsedTime );
  187.         D3DXMatrixMultiply( &m_mWorld, &m_mWorld, &m );
  188.     }
  189. };
  190.  
  191.  
  192. struct CLight
  193. {
  194.     D3DXVECTOR4   vPos;      // Position in world space
  195.     D3DXVECTOR4   vMoveDir;  // Direction in which it moves
  196.     float         fMoveDist; // Maximum distance it can move
  197.     D3DXMATRIXA16 mWorld;    // World transform matrix for the light before animation
  198.     D3DXMATRIXA16 mWorking;  // Working matrix (world transform after animation)
  199. };
  200.  
  201.  
  202. struct CTechniqueGroup
  203. {
  204.     D3DXHANDLE hRenderScene;
  205.     D3DXHANDLE hRenderLight;
  206.     D3DXHANDLE hRenderEnvMap;
  207. };
  208.  
  209.  
  210. //--------------------------------------------------------------------------------------
  211. // Global variables
  212. //--------------------------------------------------------------------------------------
  213. ID3DXFont*                   g_pFont = NULL;            // Font for drawing text
  214. ID3DXSprite*                 g_pTextSprite = NULL;      // Sprite for batching draw text calls
  215. ID3DXEffect*                 g_pEffect = NULL;          // D3DX effect interface
  216. CModelViewerCamera           g_Camera;                  // A model viewing camera
  217. bool                         g_bShowHelp = true;        // If true, it renders the UI control text
  218. CDXUTDialog                  g_HUD;                     // dialog for standard controls
  219. CLight                       g_aLights[NUM_LIGHTS];     // Parameters of light objects
  220. D3DXVECTOR4                  g_vLightIntensity;         // Light intensity
  221. CObj                         g_EnvMesh[NUM_MESHES];     // Mesh to receive environment mapping
  222. int                          g_nCurrMesh = 0;           // Index of the element in m_EnvMesh we are currently displaying
  223. CDXUTMesh                    g_Room;                    // Mesh representing room (wall, floor, ceiling)
  224. COrbiter                     g_Orbiter[sizeof(g_OrbitData) /
  225.                                         sizeof(g_OrbitData[0])]; // Orbiter meshes
  226. CDXUTMesh                    g_LightMesh;               // Mesh for the light object
  227. IDirect3DVertexDeclaration9* g_pVertDecl = NULL;        // Vertex decl for the sample
  228. IDirect3DCubeTexture9*       g_apCubeMapFp[2];          // Floating point format cube map
  229. IDirect3DCubeTexture9*       g_pCubeMap32 = NULL;       // 32-bit cube map (for fallback)
  230. IDirect3DSurface9*           g_pDepthCube = NULL;       // Depth-stencil buffer for rendering to cube texture
  231. int                          g_nNumFpCubeMap = 0;       // Number of cube maps required for using floating point
  232. CTechniqueGroup              g_aTechGroupFp[2];         // Group of techniques to use with floating pointcubemaps (2 cubes max)
  233. CTechniqueGroup              g_TechGroup32;             // Group of techniques to use with integer cubemaps
  234. D3DXHANDLE                   g_hWorldView = NULL;       // Handle for world+view matrix in effect
  235. D3DXHANDLE                   g_hProj = NULL;            // Handle for projection matrix in effect
  236. D3DXHANDLE                   g_ahtxCubeMap[2];          // Handle for the cube texture in effect
  237. D3DXHANDLE                   g_htxScene = NULL;         // Handle for the scene texture in effect
  238. D3DXHANDLE                   g_hLightIntensity = NULL;  // Handle for the light intensity in effect
  239. D3DXHANDLE                   g_hLightPosView = NULL;    // Handle for view space light positions in effect
  240. D3DXHANDLE                   g_hReflectivity = NULL;    // Handle for reflectivity in effect
  241.  
  242. int                          g_nNumCubes;               // Number of cube maps used based on current cubemap format
  243. IDirect3DCubeTexture9**      g_apCubeMap = g_apCubeMapFp;// Cube map(s) to use based on current cubemap format
  244. CTechniqueGroup              *g_pTech = g_aTechGroupFp; // Techniques to be used based on cubemap format
  245.  
  246. float                        g_fWorldRotX = 0.0f;       // World rotation state X-axis
  247. float                        g_fWorldRotY = 0.0f;       // World rotation state Y-axis
  248. bool                         g_bUseFloatCubeMap;        // Whether we use floating point format cube map
  249. float                        g_fReflectivity;           // Reflectivity value. Ranges from 0 to 1.
  250.  
  251.  
  252. //--------------------------------------------------------------------------------------
  253. // UI control IDs
  254. //--------------------------------------------------------------------------------------
  255. #define IDC_TOGGLEFULLSCREEN  1
  256. #define IDC_TOGGLEREF         3
  257. #define IDC_CHANGEDEVICE      4
  258. #define IDC_CHANGEMESH        5
  259. #define IDC_RESETPARAM        6
  260. #define IDC_SLIDERLIGHTTEXT   7
  261. #define IDC_SLIDERLIGHT       8
  262. #define IDC_SLIDERREFLECTTEXT 9
  263. #define IDC_SLIDERREFLECT     10
  264. #define IDC_CHECKHDR          11
  265.  
  266.  
  267. //--------------------------------------------------------------------------------------
  268. // Forward declarations 
  269. //--------------------------------------------------------------------------------------
  270. bool    CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed );
  271. void    CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps );
  272. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  273. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  274. void    CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  275. void    CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  276. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing );
  277. void    CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown  );
  278. void    CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl );
  279. void    CALLBACK OnLostDevice();
  280. void    CALLBACK OnDestroyDevice();
  281.  
  282. void    InitApp();
  283. HRESULT LoadMesh( IDirect3DDevice9 *pd3dDevice, LPCWSTR wszName, CDXUTMesh &Mesh );
  284. void    RenderText();
  285. void    ResetParameters();
  286. void    RenderSceneIntoCubeMap( IDirect3DDevice9 *pd3dDevice, double fTime );
  287. void    RenderScene( IDirect3DDevice9* pd3dDevice, const D3DXMATRIX *pmView, const D3DXMATRIX *pmProj, CTechniqueGroup *pTechGroup, bool bRenderEnvMappedMesh, double fTime );
  288. void    UpdateUiWithChanges();
  289.  
  290.  
  291. //--------------------------------------------------------------------------------------
  292. // Entry point to the program. Initializes everything and goes into a message processing 
  293. // loop. Idle time is used to render the scene.
  294. //--------------------------------------------------------------------------------------
  295. INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
  296. {
  297.     // Set the callback functions. These functions allow the sample framework to notify
  298.     // the application about device changes, user input, and windows messages.  The 
  299.     // callbacks are optional so you need only set callbacks for events you're interested 
  300.     // in. However, if you don't handle the device reset/lost callbacks then the sample 
  301.     // framework won't be able to reset your device since the application must first 
  302.     // release all device resources before resetting.  Likewise, if you don't handle the 
  303.     // device created/destroyed callbacks then the sample framework won't be able to 
  304.     // recreate your device resources.
  305.     DXUTSetCallbackDeviceCreated( OnCreateDevice );
  306.     DXUTSetCallbackDeviceReset( OnResetDevice );
  307.     DXUTSetCallbackDeviceLost( OnLostDevice );
  308.     DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
  309.     DXUTSetCallbackMsgProc( MsgProc );
  310.     DXUTSetCallbackKeyboard( KeyboardProc );
  311.     DXUTSetCallbackFrameRender( OnFrameRender );
  312.     DXUTSetCallbackFrameMove( OnFrameMove );
  313.  
  314.     // Show the cursor and clip it when in full screen
  315.     DXUTSetCursorSettings( true, true );
  316.  
  317.     InitApp();
  318.  
  319.     // Initialize the sample framework and create the desired Win32 window and Direct3D 
  320.     // device for the application. Calling each of these functions is optional, but they
  321.     // allow you to set several options which control the behavior of the framework.
  322.     DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
  323.     DXUTCreateWindow( L"HDRCubeMap" );
  324.     DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );
  325.  
  326.     // Pass control to the sample framework for handling the message pump and 
  327.     // dispatching render calls. The sample framework will call your FrameMove 
  328.     // and FrameRender callback when there is idle time between handling window messages.
  329.     DXUTMainLoop();
  330.  
  331.     // Perform any application-level cleanup here. Direct3D device resources are released within the
  332.     // appropriate callback functions and therefore don't require any cleanup code here.
  333.  
  334.     return DXUTGetExitCode();
  335. }
  336.  
  337.  
  338. //--------------------------------------------------------------------------------------
  339. // Initialize the app 
  340. //--------------------------------------------------------------------------------------
  341. void InitApp()
  342. {
  343.     // Change CheckBox default visual style
  344.     CDXUTElement* pElement = g_HUD.GetDefaultElement( DXUT_CONTROL_CHECKBOX, 0 );
  345.     pElement->FontColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 255, 0, 255, 0 );
  346.  
  347.     // Change Static default visual style
  348.     pElement = g_HUD.GetDefaultElement( DXUT_CONTROL_STATIC, 0 );
  349.     pElement->dwTextFormat = DT_LEFT | DT_VCENTER;
  350.     pElement->FontColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 255, 0, 255, 0 );
  351.     
  352.     // Initialize dialogs
  353.     g_HUD.SetCallback( OnGUIEvent ); int iY = 10; 
  354.     g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 35, iY, 125, 22 );
  355.     g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 35, iY += 24, 125, 22 );
  356.     g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 35, iY += 24, 125, 22 );
  357.  
  358.     g_HUD.AddButton( IDC_CHANGEMESH, L"Change Mesh (N)", 35, iY += 24, 125, 22, L'N' );
  359.     g_HUD.AddButton( IDC_RESETPARAM, L"Reset Parameters (R)", 35, iY += 24, 125, 22, L'R' );
  360.     g_HUD.AddCheckBox( IDC_CHECKHDR, L"Use HDR Texture (F)", 35, iY += 24, 130, 22, true, L'F' );
  361.     g_HUD.AddStatic( IDC_SLIDERLIGHTTEXT, L"Light Intensity", 35, iY += 24, 125, 16 );
  362.     g_HUD.AddSlider( IDC_SLIDERLIGHT, 35, iY += 17, 125, 22, 0, 1500 );
  363.     g_HUD.AddStatic( IDC_SLIDERREFLECTTEXT, L"Reflectivity", 35, iY += 24, 125, 16 );
  364.     g_HUD.AddSlider( IDC_SLIDERREFLECT, 35, iY += 17, 125, 22, 0, 100 );
  365.     
  366.     ResetParameters();
  367.  
  368.     // Initialize camera parameters
  369.     g_Camera.SetModelCenter( D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) );
  370.     g_Camera.SetRadius( 3.0f );
  371.     g_Camera.SetEnablePositionMovement( false );
  372.  
  373.     // Set the light positions
  374.     g_aLights[0].vPos = D3DXVECTOR4( -3.5f, 2.3f, -4.0f, 1.0f );
  375.     g_aLights[0].vMoveDir = D3DXVECTOR4( 0.0f, 0.0f, 1.0f, 0.0f );
  376.     g_aLights[0].fMoveDist = 8.0f;
  377. #if NUM_LIGHTS > 1
  378.     g_aLights[1].vPos = D3DXVECTOR4(  3.5f, 2.3f,  4.0f, 1.0f );
  379.     g_aLights[1].vMoveDir = D3DXVECTOR4( 0.0f, 0.0f, -1.0f, 0.0f );
  380.     g_aLights[1].fMoveDist = 8.0f;
  381. #endif
  382. #if NUM_LIGHTS > 2
  383.     g_aLights[2].vPos = D3DXVECTOR4( -3.5f, 2.3f,  4.0f, 1.0f );
  384.     g_aLights[2].vMoveDir = D3DXVECTOR4( 1.0f, 0.0f, 0.0f, 0.0f );
  385.     g_aLights[2].fMoveDist = 7.0f;
  386. #endif
  387. #if NUM_LIGHTS > 3
  388.     g_aLights[3].vPos = D3DXVECTOR4(  3.5f, 2.3f, -4.0f, 1.0f );
  389.     g_aLights[3].vMoveDir = D3DXVECTOR4( -1.0f, 0.0f, 0.0f, 0.0f );
  390.     g_aLights[3].fMoveDist = 7.0f;
  391. #endif
  392. }
  393.  
  394.  
  395. //--------------------------------------------------------------------------------------
  396. // Called during device initialization, this code checks the device for some 
  397. // minimum set of capabilities, and rejects those that don't pass by returning false.
  398. //--------------------------------------------------------------------------------------
  399. bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, 
  400.                                   D3DFORMAT BackBufferFormat, bool bWindowed )
  401. {
  402.     // Skip backbuffer formats that don't support alpha blending
  403.     IDirect3D9* pD3D = DXUTGetD3DObject(); 
  404.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  405.                     AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, 
  406.                     D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
  407.         return false;
  408.  
  409.     // Must support cube textures
  410.     if( !( pCaps->TextureCaps & D3DPTEXTURECAPS_CUBEMAP ) )
  411.         return false;
  412.  
  413.     // Must support pixel shader 2.0
  414.     if( pCaps->PixelShaderVersion < D3DPS_VERSION( 2, 0 ) )
  415.         return false;
  416.  
  417.     // need to support D3DFMT_A16B16G16R16F render target
  418.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  419.                     AdapterFormat, D3DUSAGE_RENDERTARGET, 
  420.                     D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F ) ) )
  421.     {
  422.         // If not, need to support D3DFMT_G16R16F render target as fallback
  423.         if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  424.                         AdapterFormat, D3DUSAGE_RENDERTARGET, 
  425.                         D3DRTYPE_CUBETEXTURE, D3DFMT_G16R16F ) ) )
  426.             return false;
  427.     }
  428.  
  429.     // need to support D3DFMT_A8R8G8B8 render target
  430.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  431.                     AdapterFormat, D3DUSAGE_RENDERTARGET, 
  432.                     D3DRTYPE_CUBETEXTURE, D3DFMT_A8R8G8B8 ) ) )
  433.     {
  434.         return false;
  435.     }
  436.  
  437.     return true;
  438. }
  439.  
  440.  
  441. //--------------------------------------------------------------------------------------
  442. // This callback function is called immediately before a device is created to allow the 
  443. // application to modify the device settings. The supplied pDeviceSettings parameter 
  444. // contains the settings that the framework has selected for the new device, and the 
  445. // application can make any desired changes directly to this structure.  Note however that 
  446. // the sample framework will not correct invalid device settings so care must be taken 
  447. // to return valid device settings, otherwise IDirect3D9::CreateDevice() will fail.  
  448. //--------------------------------------------------------------------------------------
  449. void CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps )
  450. {
  451.     // Initialize the number of cube maps required when using floating point format
  452.     IDirect3D9* pD3D = DXUTGetD3DObject(); 
  453.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  454.                                          pDeviceSettings->AdapterFormat, D3DUSAGE_RENDERTARGET, 
  455.                                          D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F ) ) )
  456.     {
  457.         g_nNumCubes = g_nNumFpCubeMap = 2;
  458.     }
  459.     else
  460.     {
  461.         g_nNumCubes = g_nNumFpCubeMap = 1;
  462.     }
  463.  
  464.     // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW 
  465.     // then switch to SWVP.
  466.     if( (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 ||
  467.          pCaps->VertexShaderVersion < D3DVS_VERSION(1,1) )
  468.     {
  469.         pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  470.     }
  471.     else
  472.     {
  473.         pDeviceSettings->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  474.     }
  475.  
  476.     // This application is designed to work on a pure device by not using 
  477.     // IDirect3D9::Get*() methods, so create a pure device if supported and using HWVP.
  478.     if ((pCaps->DevCaps & D3DDEVCAPS_PUREDEVICE) != 0 && 
  479.         (pDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0 )
  480.         pDeviceSettings->BehaviorFlags |= D3DCREATE_PUREDEVICE;
  481.  
  482.     // Debugging vertex shaders requires either REF or software vertex processing 
  483.     // and debugging pixel shaders requires REF.  
  484. #ifdef DEBUG_VS
  485.     if( pDeviceSettings->DeviceType != D3DDEVTYPE_REF )
  486.     {
  487.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
  488.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_PUREDEVICE;                            
  489.         pDeviceSettings->BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  490.     }
  491. #endif
  492. #ifdef DEBUG_PS
  493.     pDeviceSettings->DeviceType = D3DDEVTYPE_REF;
  494. #endif
  495. }
  496.  
  497.  
  498. //-----------------------------------------------------------------------------
  499. // Reset light and material parameters to default values
  500. //-----------------------------------------------------------------------------
  501. void ResetParameters()
  502. {
  503.     HRESULT hr;
  504.  
  505.     g_bUseFloatCubeMap = true;
  506.     g_fReflectivity    = 0.4f;
  507.     g_vLightIntensity  = D3DXVECTOR4( 24.0f, 24.0f, 24.0f, 24.0f );
  508.  
  509.     if( g_pEffect )
  510.     {
  511.         V( g_pEffect->SetFloat( g_hReflectivity, g_fReflectivity ) );
  512.         V( g_pEffect->SetVector( g_hLightIntensity, &g_vLightIntensity ) );
  513.     }
  514.  
  515.     UpdateUiWithChanges();
  516. }
  517.  
  518.  
  519. //--------------------------------------------------------------------------------------
  520. // Write the updated values to the static UI controls
  521. void UpdateUiWithChanges()
  522. {
  523.     CDXUTStatic *pStatic = g_HUD.GetStatic( IDC_SLIDERLIGHTTEXT );
  524.     if( pStatic )
  525.     {
  526.         WCHAR wszText[128];
  527.         swprintf( wszText, L"Light intensity: %0.2f", g_vLightIntensity.x );
  528.         pStatic->SetText( wszText );
  529.     }
  530.     pStatic = g_HUD.GetStatic( IDC_SLIDERREFLECTTEXT );
  531.     if( pStatic )
  532.     {
  533.         WCHAR wszText[128];
  534.         swprintf( wszText, L"Reflectivity: %0.2f", g_fReflectivity );
  535.         pStatic->SetText( wszText );
  536.     }
  537.     CDXUTSlider *pSlider = g_HUD.GetSlider( IDC_SLIDERLIGHT );
  538.     if( pSlider )
  539.     {
  540.         pSlider->SetValue( int( g_vLightIntensity.x * 10.0f ) );
  541.     }
  542.     pSlider = g_HUD.GetSlider( IDC_SLIDERREFLECT );
  543.     if( pSlider )
  544.     {
  545.         pSlider->SetValue( int( g_fReflectivity * 100.0f ) );
  546.     }
  547.     CDXUTCheckBox *pCheck = g_HUD.GetCheckBox( IDC_CHECKHDR );
  548.     if( pCheck )
  549.         pCheck->SetChecked( g_bUseFloatCubeMap );
  550. }
  551.  
  552.  
  553. //--------------------------------------------------------------------------------------
  554. // This callback function will be called immediately after the Direct3D device has been 
  555. // created, which will happen during application initialization and windowed/full screen 
  556. // toggles. This is the best location to create D3DPOOL_MANAGED resources since these 
  557. // resources need to be reloaded whenever the device is destroyed. Resources created  
  558. // here should be released in the OnDestroyDevice callback. 
  559. //--------------------------------------------------------------------------------------
  560. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  561. {
  562.     HRESULT hr;
  563.  
  564.     // Initialize the font
  565.     V_RETURN( D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, 
  566.                          OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
  567.                          L"Arial", &g_pFont ) );
  568.  
  569.     // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the 
  570.     // shader debugger. Debugging vertex shaders requires either REF or software vertex 
  571.     // processing, and debugging pixel shaders requires REF.  The 
  572.     // D3DXSHADER_FORCE_*_SOFTWARE_NOOPT flag improves the debug experience in the 
  573.     // shader debugger.  It enables source level debugging, prevents instruction 
  574.     // reordering, prevents dead code elimination, and forces the compiler to compile 
  575.     // against the next higher available software target, which ensures that the 
  576.     // unoptimized shaders do not exceed the shader model limitations.  Setting these 
  577.     // flags will cause slower rendering since the shaders will be unoptimized and 
  578.     // forced into software.  See the DirectX documentation for more information about 
  579.     // using the shader debugger.
  580.     DWORD dwShaderFlags = 0;
  581.     #ifdef DEBUG_VS
  582.         dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
  583.     #endif
  584.     #ifdef DEBUG_PS
  585.         dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
  586.     #endif
  587.  
  588.     // Read the D3DX effect file
  589.     WCHAR str[MAX_PATH];
  590.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"HDRCubeMap.fx" ) );
  591.  
  592.     // If this fails, there should be debug output as to 
  593.     // they the .fx file failed to compile
  594.     V_RETURN( D3DXCreateEffectFromFile( pd3dDevice, str, NULL, NULL, dwShaderFlags, 
  595.                                         NULL, &g_pEffect, NULL ) );
  596.  
  597.     g_hWorldView           = g_pEffect->GetParameterByName( NULL, "g_mWorldView" );
  598.     g_hProj                = g_pEffect->GetParameterByName( NULL, "g_mProj" );
  599.     g_ahtxCubeMap[0]       = g_pEffect->GetParameterByName( NULL, "g_txCubeMap" );
  600.     g_ahtxCubeMap[1]       = g_pEffect->GetParameterByName( NULL, "g_txCubeMap2" );
  601.     g_htxScene             = g_pEffect->GetParameterByName( NULL, "g_txScene" );
  602.     g_hLightIntensity      = g_pEffect->GetParameterByName( NULL, "g_vLightIntensity" );
  603.     g_hLightPosView        = g_pEffect->GetParameterByName( NULL, "g_vLightPosView" );
  604.     g_hReflectivity        = g_pEffect->GetParameterByName( NULL, "g_fReflectivity" );
  605.  
  606.     // Determine the technique to render with
  607.  
  608.     // Integer cube map
  609.     g_TechGroup32.hRenderScene = g_pEffect->GetTechniqueByName( "RenderScene" );
  610.     g_TechGroup32.hRenderLight = g_pEffect->GetTechniqueByName( "RenderLight" );
  611.     g_TechGroup32.hRenderEnvMap = g_pEffect->GetTechniqueByName( "RenderHDREnvMap" );
  612.  
  613.     ZeroMemory( g_aTechGroupFp, sizeof(g_aTechGroupFp) );
  614.     if( g_nNumFpCubeMap == 2 )
  615.     {
  616.         // Two floating point G16R16F cube maps
  617.         g_aTechGroupFp[0].hRenderScene = g_pEffect->GetTechniqueByName( "RenderSceneFirstHalf" );
  618.         g_aTechGroupFp[0].hRenderLight = g_pEffect->GetTechniqueByName( "RenderLightFirstHalf" );
  619.         g_aTechGroupFp[0].hRenderEnvMap = g_pEffect->GetTechniqueByName( "RenderHDREnvMap2Tex" );
  620.         g_aTechGroupFp[1].hRenderScene = g_pEffect->GetTechniqueByName( "RenderSceneSecondHalf" );
  621.         g_aTechGroupFp[1].hRenderLight = g_pEffect->GetTechniqueByName( "RenderLightSecondHalf" );
  622.         g_aTechGroupFp[1].hRenderEnvMap = g_pEffect->GetTechniqueByName( "RenderHDREnvMap2Tex" );
  623.     } else
  624.     {
  625.         // Single floating point cube map
  626.         g_aTechGroupFp[0].hRenderScene = g_pEffect->GetTechniqueByName( "RenderScene" );
  627.         g_aTechGroupFp[0].hRenderLight = g_pEffect->GetTechniqueByName( "RenderLight" );
  628.         g_aTechGroupFp[0].hRenderEnvMap = g_pEffect->GetTechniqueByName( "RenderHDREnvMap" );
  629.     }
  630.  
  631.     // Initialize reflectivity
  632.     V_RETURN( g_pEffect->SetFloat( g_hReflectivity, g_fReflectivity ) );
  633.  
  634.     // Initialize light intensity
  635.     V_RETURN( g_pEffect->SetVector( g_hLightIntensity, &g_vLightIntensity ) );
  636.  
  637.     // Create vertex declaration
  638.     V_RETURN( pd3dDevice->CreateVertexDeclaration( g_aVertDecl, &g_pVertDecl ) );
  639.  
  640.     // Load the mesh
  641.     for( int i = 0; i < NUM_MESHES; ++i )
  642.     {
  643.         if( FAILED( LoadMesh( pd3dDevice, g_atszMeshFileName[i], g_EnvMesh[i].m_Mesh ) ) )
  644.             return DXUTERR_MEDIANOTFOUND;
  645.         g_EnvMesh[i].WorldCenterAndScaleToRadius( 1.0f );  // Scale to radius of 1
  646.     }
  647.     // Load the room object
  648.     if( FAILED( LoadMesh( pd3dDevice, L"room.x", g_Room ) ) )
  649.         return DXUTERR_MEDIANOTFOUND;
  650.     // Load the light object
  651.     if( FAILED( LoadMesh( pd3dDevice, L"misc\\sphere0.x", g_LightMesh ) ) )
  652.         return DXUTERR_MEDIANOTFOUND;
  653.     // Initialize the world matrix for the lights
  654.     D3DXVECTOR3 vCtr;
  655.     float fRadius;
  656.     if( FAILED( ComputeBoundingSphere( g_LightMesh, &vCtr, &fRadius ) ) )
  657.         return E_FAIL;
  658.     D3DXMATRIXA16 mWorld, m;
  659.     D3DXMatrixTranslation( &mWorld, -vCtr.x, -vCtr.y, -vCtr.z );
  660.     D3DXMatrixScaling( &m, LIGHTMESH_RADIUS / fRadius,
  661.                             LIGHTMESH_RADIUS / fRadius,
  662.                             LIGHTMESH_RADIUS / fRadius );
  663.     D3DXMatrixMultiply( &mWorld, &mWorld, &m );
  664.     for( i = 0; i < NUM_LIGHTS; ++i )
  665.     {
  666.         D3DXMatrixTranslation( &m, g_aLights[i].vPos.x,
  667.                                     g_aLights[i].vPos.y,
  668.                                     g_aLights[i].vPos.z );
  669.         D3DXMatrixMultiply( &g_aLights[i].mWorld, &mWorld, &m );
  670.     }
  671.  
  672.     // Orbiter
  673.     for( i = 0; i < sizeof(g_Orbiter) / sizeof(g_Orbiter[0]); ++i )
  674.     {
  675.         if( FAILED( LoadMesh( pd3dDevice, g_OrbitData[i].tszXFile, g_Orbiter[i].m_Mesh ) ) )
  676.             return DXUTERR_MEDIANOTFOUND;
  677.  
  678.         g_Orbiter[i].WorldCenterAndScaleToRadius( 0.7f );
  679.         D3DXVECTOR3 vAxis( g_OrbitData[i].vAxis );
  680.         g_Orbiter[i].SetOrbit( vAxis, g_OrbitData[i].fRadius, g_OrbitData[i].fSpeed );
  681.     }
  682.  
  683.     // World transform to identity
  684.     D3DXMATRIXA16 mIdent;
  685.     D3DXMatrixIdentity( &mIdent );
  686.     V_RETURN( pd3dDevice->SetTransform( D3DTS_WORLD, &mIdent ) );
  687.  
  688.     // Setup the camera's view parameters
  689.     D3DXVECTOR3 vFromPt( 0.0f, 0.0f, -2.5f );
  690.     D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
  691.     g_Camera.SetViewParams( &vFromPt, &vLookatPt );
  692.  
  693.     return S_OK;
  694. }
  695.  
  696.  
  697. //--------------------------------------------------------------------------------------
  698. // Load mesh from file and convert vertices to our format
  699. //--------------------------------------------------------------------------------------
  700. HRESULT LoadMesh( IDirect3DDevice9 *pd3dDevice, LPCWSTR wszName, CDXUTMesh &Mesh )
  701. {
  702.     HRESULT hr;
  703.  
  704.     if( FAILED( hr = Mesh.Create( pd3dDevice, wszName ) ) )
  705.         return hr;
  706.     hr = Mesh.SetVertexDecl( pd3dDevice, g_aVertDecl );
  707.  
  708.     return hr;
  709. }
  710.  
  711.  
  712. //--------------------------------------------------------------------------------------
  713. // This callback function will be called immediately after the Direct3D device has been 
  714. // reset, which will happen after a lost device scenario. This is the best location to 
  715. // create D3DPOOL_DEFAULT resources since these resources need to be reloaded whenever 
  716. // the device is lost. Resources created here should be released in the OnLostDevice 
  717. // callback. 
  718. //--------------------------------------------------------------------------------------
  719. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, 
  720.                                 const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  721. {
  722.     HRESULT hr;
  723.  
  724.     if( g_pFont )
  725.         V_RETURN( g_pFont->OnResetDevice() );
  726.     if( g_pEffect )
  727.         V_RETURN( g_pEffect->OnResetDevice() );
  728.  
  729.     // Create a sprite to help batch calls when drawing many lines of text
  730.     V_RETURN( D3DXCreateSprite( pd3dDevice, &g_pTextSprite ) );
  731.  
  732.     // Setup the camera's projection parameters
  733.     float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height;
  734.     g_Camera.SetProjParams( D3DX_PI/4, fAspectRatio, 0.1f, 1000.0f );
  735.     g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
  736.  
  737.     g_HUD.SetLocation( pBackBufferSurfaceDesc->Width-170, 0 );
  738.     g_HUD.SetSize( 170, 170 );
  739.     int iY = pBackBufferSurfaceDesc->Height - 170;
  740.     CDXUTControl *pControl;
  741.     if( ( pControl = g_HUD.GetControl( IDC_CHECKHDR ) ) != NULL )
  742.         pControl->SetLocation( 35, iY );
  743.     if( ( pControl = g_HUD.GetControl( IDC_CHANGEMESH ) ) != NULL )
  744.         pControl->SetLocation( 35, iY += 24 );
  745.     if( ( pControl = g_HUD.GetControl( IDC_RESETPARAM ) ) != NULL )
  746.         pControl->SetLocation( 35, iY += 24 );
  747.     if( ( pControl = g_HUD.GetControl( IDC_SLIDERLIGHTTEXT ) ) != NULL )
  748.         pControl->SetLocation( 35, iY += 35 );
  749.     if( ( pControl = g_HUD.GetControl( IDC_SLIDERLIGHT ) ) != NULL )
  750.         pControl->SetLocation( 35, iY += 17 );
  751.     if( ( pControl = g_HUD.GetControl( IDC_SLIDERREFLECTTEXT ) ) != NULL )
  752.         pControl->SetLocation( 35, iY += 24 );
  753.     if( ( pControl = g_HUD.GetControl( IDC_SLIDERREFLECT ) ) != NULL )
  754.         pControl->SetLocation( 35, iY += 17 );
  755.  
  756.     // Restore meshes
  757.     for( int i = 0; i < NUM_MESHES; ++i )
  758.         g_EnvMesh[i].m_Mesh.RestoreDeviceObjects( pd3dDevice );
  759.     g_Room.RestoreDeviceObjects( pd3dDevice );
  760.     g_LightMesh.RestoreDeviceObjects( pd3dDevice );
  761.     for( int i = 0; i < sizeof(g_Orbiter) / sizeof(g_Orbiter[0]); ++i )
  762.         g_Orbiter[i].m_Mesh.RestoreDeviceObjects( pd3dDevice );
  763.  
  764.     // Create the cube textures
  765.     ZeroMemory( g_apCubeMapFp, sizeof( g_apCubeMapFp ) );
  766.     hr = pd3dDevice->CreateCubeTexture( ENVMAPSIZE,
  767.                                         1,
  768.                                         D3DUSAGE_RENDERTARGET,
  769.                                         D3DFMT_A16B16G16R16F,
  770.                                         D3DPOOL_DEFAULT,
  771.                                         &g_apCubeMapFp[0],
  772.                                         NULL );
  773.     if( FAILED( hr ) )
  774.     {
  775.         // Create 2 G16R16 textures as fallback
  776.         V_RETURN( pd3dDevice->CreateCubeTexture( ENVMAPSIZE,
  777.                                                  1,
  778.                                                  D3DUSAGE_RENDERTARGET,
  779.                                                  D3DFMT_G16R16F,
  780.                                                  D3DPOOL_DEFAULT,
  781.                                                  &g_apCubeMapFp[0],
  782.                                                  NULL ) );
  783.         V_RETURN( pd3dDevice->CreateCubeTexture( ENVMAPSIZE,
  784.                                                  1,
  785.                                                  D3DUSAGE_RENDERTARGET,
  786.                                                  D3DFMT_G16R16F,
  787.                                                  D3DPOOL_DEFAULT,
  788.                                                  &g_apCubeMapFp[1],
  789.                                                  NULL ) );
  790.     }
  791.  
  792.     V_RETURN( pd3dDevice->CreateCubeTexture( ENVMAPSIZE,
  793.                                              1,
  794.                                              D3DUSAGE_RENDERTARGET,
  795.                                              D3DFMT_A8R8G8B8,
  796.                                              D3DPOOL_DEFAULT,
  797.                                              &g_pCubeMap32,
  798.                                              NULL ) );
  799.  
  800.     // Create the stencil buffer to be used with the cube textures
  801.     // Create the depth-stencil buffer to be used with the shadow map
  802.     // We do this to ensure that the depth-stencil buffer is large
  803.     // enough and has correct multisample type/quality when rendering
  804.     // the shadow map.  The default depth-stencil buffer created during
  805.     // device creation will not be large enough if the user resizes the
  806.     // window to a very small size.  Furthermore, if the device is created
  807.     // with multisampling, the default depth-stencil buffer will not
  808.     // work with the shadow map texture because texture render targets
  809.     // do not support multisample.
  810.     DXUTDeviceSettings d3dSettings = DXUTGetDeviceSettings();
  811.     V_RETURN( pd3dDevice->CreateDepthStencilSurface( ENVMAPSIZE,
  812.                                                      ENVMAPSIZE,
  813.                                                      d3dSettings.pp.AutoDepthStencilFormat,
  814.                                                      D3DMULTISAMPLE_NONE,
  815.                                                      0,
  816.                                                      TRUE,
  817.                                                      &g_pDepthCube,
  818.                                                      NULL ) );
  819.  
  820.     return S_OK;
  821. }
  822.  
  823.  
  824. //--------------------------------------------------------------------------------------
  825. // This callback function will be called once at the beginning of every frame. This is the
  826. // best location for your application to handle updates to the scene, but is not 
  827. // intended to contain actual rendering calls, which should instead be placed in the 
  828. // OnFrameRender callback.  
  829. //--------------------------------------------------------------------------------------
  830. void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  831. {
  832.     // Update the camera's position based on user input 
  833.     g_Camera.FrameMove( fElapsedTime );
  834.  
  835.     for( int i = 0; i < sizeof(g_Orbiter) / sizeof(g_Orbiter[0]); ++i )
  836.         g_Orbiter[i].Orbit( fElapsedTime );
  837. }
  838.  
  839.  
  840. //--------------------------------------------------------------------------------------
  841. // This callback function will be called at the end of every frame to perform all the 
  842. // rendering calls for the scene, and it will also be called if the window needs to be 
  843. // repainted. After this function has returned, the sample framework will call 
  844. // IDirect3DDevice9::Present to display the contents of the next buffer in the swap chain
  845. //--------------------------------------------------------------------------------------
  846. void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  847. {
  848.     HRESULT hr;
  849.  
  850.     RenderSceneIntoCubeMap( pd3dDevice, fTime );
  851.  
  852.     // Clear the render buffers
  853.     V( pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
  854.                           0x000000ff, 1.0f, 0L ) );
  855.  
  856.     // Begin the scene
  857.     if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  858.     {
  859.         RenderScene( pd3dDevice, g_Camera.GetViewMatrix(), g_Camera.GetProjMatrix(), g_pTech, true, fTime );
  860.  
  861.         // Render stats and help text
  862.         RenderText();
  863.  
  864.         g_HUD.OnRender( fElapsedTime );
  865.  
  866.         pd3dDevice->EndScene();
  867.     }
  868. }
  869.  
  870.  
  871. //--------------------------------------------------------------------------------------
  872. // Set up the cube map by rendering the scene into it.
  873. //--------------------------------------------------------------------------------------
  874. void RenderSceneIntoCubeMap( IDirect3DDevice9 *pd3dDevice, double fTime )
  875. {
  876.     HRESULT hr;
  877.  
  878.     // The projection matrix has a FOV of 90 degrees and asp ratio of 1
  879.     D3DXMATRIXA16 mProj;
  880.     D3DXMatrixPerspectiveFovLH( &mProj, D3DX_PI * 0.5f, 1.0f, 0.01f, 100.0f );
  881.  
  882.     D3DXMATRIXA16 mViewDir( *g_Camera.GetViewMatrix() );
  883.     mViewDir._41 = mViewDir._42 = mViewDir._43 = 0.0f;
  884.  
  885.     LPDIRECT3DSURFACE9 pRTOld = NULL;
  886.     V( pd3dDevice->GetRenderTarget( 0, &pRTOld ) );
  887.     LPDIRECT3DSURFACE9 pDSOld = NULL;
  888.     if( SUCCEEDED( pd3dDevice->GetDepthStencilSurface( &pDSOld ) ) )
  889.     {
  890.         // If the device has a depth-stencil buffer, use
  891.         // the depth stencil buffer created for the cube textures.
  892.         V( pd3dDevice->SetDepthStencilSurface( g_pDepthCube ) );
  893.     }
  894.  
  895.     for( int nCube = 0; nCube < g_nNumCubes; ++nCube )
  896.         for( int nFace = 0; nFace < 6; ++nFace )
  897.         {
  898.             LPDIRECT3DSURFACE9 pSurf;
  899.  
  900.             V( g_apCubeMap[nCube]->GetCubeMapSurface( (D3DCUBEMAP_FACES)nFace, 0, &pSurf ) );
  901.             V( pd3dDevice->SetRenderTarget( 0, pSurf ) );
  902.             SAFE_RELEASE( pSurf );
  903.  
  904.             D3DXMATRIXA16 mView = DXUTGetCubeMapViewMatrix( nFace );
  905.             D3DXMatrixMultiply( &mView, &mViewDir, &mView );
  906.  
  907.             V( pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER,
  908.                                 0x000000ff, 1.0f, 0L ) );
  909.  
  910.             // Begin the scene
  911.             if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  912.             {
  913.                 RenderScene( pd3dDevice, &mView, &mProj, &g_pTech[nCube], false, fTime );
  914.  
  915.                 // End the scene.
  916.                 pd3dDevice->EndScene();
  917.             }
  918.         }
  919.  
  920.     // Restore depth-stencil buffer and render target
  921.     if( pDSOld )
  922.     {
  923.         V( pd3dDevice->SetDepthStencilSurface( pDSOld ) );
  924.         SAFE_RELEASE( pDSOld );
  925.     }
  926.     V( pd3dDevice->SetRenderTarget( 0, pRTOld ) );
  927.     SAFE_RELEASE( pRTOld );
  928. }
  929.  
  930.  
  931. //--------------------------------------------------------------------------------------
  932. // Renders the scene with a specific view and projection matrix.
  933. //--------------------------------------------------------------------------------------
  934. void RenderScene( IDirect3DDevice9 *pd3dDevice, const D3DXMATRIX *pmView, const D3DXMATRIX *pmProj,
  935.                   CTechniqueGroup *pTechGroup, bool bRenderEnvMappedMesh, double fTime )
  936. {
  937.     HRESULT hr;
  938.     UINT p, cPass;
  939.     D3DXMATRIXA16 mWorldView;
  940.  
  941.     V( g_pEffect->SetMatrix( g_hProj, pmProj ) );
  942.  
  943.     // Write camera-space light positions to effect
  944.     D3DXVECTOR4 avLightPosView[NUM_LIGHTS];
  945.     for( int i = 0; i < NUM_LIGHTS; ++i )
  946.     {
  947.         // Animate the lights
  948.         float fDisp = ( 1.0f + cosf( fmodf( (float)fTime, D3DX_PI ) ) ) * 0.5f * g_aLights[i].fMoveDist; // Distance to move
  949.         D3DXVECTOR4 vMove = g_aLights[i].vMoveDir * fDisp;  // In vector form
  950.         D3DXMatrixTranslation( &g_aLights[i].mWorking, vMove.x, vMove.y, vMove.z ); // Matrix form
  951.         D3DXMatrixMultiply( &g_aLights[i].mWorking, &g_aLights[i].mWorld, &g_aLights[i].mWorking );
  952.         vMove += g_aLights[i].vPos;  // Animated world coordinates
  953.         D3DXVec4Transform( &avLightPosView[i], &vMove, pmView );
  954.     }
  955.     V( g_pEffect->SetVectorArray( g_hLightPosView, avLightPosView, NUM_LIGHTS ) );
  956.  
  957.     //
  958.     // Render the environment-mapped mesh if specified
  959.     //
  960.  
  961.     if( bRenderEnvMappedMesh )
  962.     {
  963.         V( g_pEffect->SetTechnique( pTechGroup->hRenderEnvMap ) );
  964.  
  965.         // Combine the offset and scaling transformation with
  966.         // rotation from the camera to form the final
  967.         // world transformation matrix.
  968.         D3DXMatrixMultiply( &mWorldView, &g_EnvMesh[g_nCurrMesh].m_mWorld, g_Camera.GetWorldMatrix() );
  969.         D3DXMatrixMultiply( &mWorldView, &mWorldView, pmView );
  970.         V( g_pEffect->SetMatrix( g_hWorldView, &mWorldView ) );
  971.  
  972.         V( g_pEffect->Begin( &cPass, 0 ) );
  973.  
  974.         for( int i = 0; i < g_nNumCubes; ++i )
  975.             V( g_pEffect->SetTexture( g_ahtxCubeMap[i], g_apCubeMap[i] ) );
  976.  
  977.         for( p = 0; p < cPass; ++p )
  978.         {
  979.             V( g_pEffect->BeginPass( p ) );
  980.             LPD3DXMESH pMesh = g_EnvMesh[g_nCurrMesh].m_Mesh.GetLocalMesh();
  981.             for( DWORD i = 0; i < g_EnvMesh[g_nCurrMesh].m_Mesh.m_dwNumMaterials; ++i )
  982.                 V( pMesh->DrawSubset( i ) );
  983.             V( g_pEffect->EndPass() );
  984.         }
  985.         V( g_pEffect->End() );
  986.     }
  987.  
  988.     //
  989.     // Render light spheres
  990.     //
  991.  
  992.     V( g_pEffect->SetTechnique( pTechGroup->hRenderLight ) );
  993.  
  994.     V( g_pEffect->Begin( &cPass, 0 ) );
  995.     for( p = 0; p < cPass; ++p )
  996.     {
  997.         V( g_pEffect->BeginPass( p ) );
  998.  
  999.         for( int i = 0; i < NUM_LIGHTS; ++i )
  1000.         {
  1001.             D3DXMatrixMultiply( &mWorldView, &g_aLights[i].mWorking, pmView );
  1002.             V( g_pEffect->SetMatrix( g_hWorldView, &mWorldView ) );
  1003.             V( g_pEffect->CommitChanges() );
  1004.             V( g_LightMesh.Render( pd3dDevice ) );
  1005.         }
  1006.         V( g_pEffect->EndPass() );
  1007.     }
  1008.     V( g_pEffect->End() );
  1009.  
  1010.     //
  1011.     // Render the rest of the scene
  1012.     //
  1013.  
  1014.     V( g_pEffect->SetTechnique( pTechGroup->hRenderScene ) );
  1015.  
  1016.     V( g_pEffect->Begin( &cPass, 0 ) );
  1017.     for( p = 0; p < cPass; ++p )
  1018.     {
  1019.         LPD3DXMESH pMeshObj;
  1020.         V( g_pEffect->BeginPass( p ) );
  1021.  
  1022.         //
  1023.         // Orbiters
  1024.         //
  1025.         for( int i = 0; i < sizeof(g_Orbiter) / sizeof(g_Orbiter[0]); ++i )
  1026.         {
  1027.             D3DXMatrixMultiply( &mWorldView, &g_Orbiter[i].m_mWorld, pmView );
  1028.             V( g_pEffect->SetMatrix( g_hWorldView, &mWorldView ) );
  1029.             // Obtain the D3DX mesh object
  1030.             pMeshObj = g_Orbiter[i].m_Mesh.GetLocalMesh();
  1031.             // Iterate through each subset and render with its texture
  1032.             for( DWORD m = 0; m < g_Orbiter[i].m_Mesh.m_dwNumMaterials; ++m )
  1033.             {
  1034.                 V( g_pEffect->SetTexture( g_htxScene, g_Orbiter[i].m_Mesh.m_pTextures[m] ) );
  1035.                 V( g_pEffect->CommitChanges() );
  1036.                 V( pMeshObj->DrawSubset( m ) );
  1037.             }
  1038.         }
  1039.  
  1040.         //
  1041.         // The room object (walls, floor, ceiling)
  1042.         //
  1043.  
  1044.         V( g_pEffect->SetMatrix( g_hWorldView, pmView ) );
  1045.         pMeshObj = g_Room.GetLocalMesh();
  1046.         // Iterate through each subset and render with its texture
  1047.         for( DWORD m = 0; m < g_Room.m_dwNumMaterials; ++m )
  1048.         {
  1049.             V( g_pEffect->SetTexture( g_htxScene, g_Room.m_pTextures[m] ) );
  1050.             V( g_pEffect->CommitChanges() );
  1051.             V( pMeshObj->DrawSubset( m ) );
  1052.         }
  1053.         V( g_pEffect->EndPass() );
  1054.     }
  1055.     V( g_pEffect->End() );
  1056. }
  1057.  
  1058.  
  1059. //--------------------------------------------------------------------------------------
  1060. // Render the help and statistics text. This function uses the ID3DXFont interface for 
  1061. // efficient text rendering.
  1062. //--------------------------------------------------------------------------------------
  1063. void RenderText()
  1064. {
  1065.     // The helper object simply helps keep track of text position, and color
  1066.     // and then it calls pFont->DrawText( m_pSprite, strMsg, -1, &rc, DT_NOCLIP, m_clr );
  1067.     // If NULL is passed in as the sprite object, then it will work however the 
  1068.     // pFont->DrawText() will not be batched together.  Batching calls will improves performance.
  1069.     CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 15 );
  1070.  
  1071.     // Output statistics
  1072.     txtHelper.Begin();
  1073.     txtHelper.SetInsertionPos( 5, 5 );
  1074.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
  1075.     txtHelper.DrawTextLine( DXUTGetFrameStats() );
  1076.     txtHelper.DrawTextLine( DXUTGetDeviceStats() );
  1077.  
  1078.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
  1079.     
  1080.     // Draw help
  1081.     const D3DSURFACE_DESC* pd3dsdBackBuffer = DXUTGetBackBufferSurfaceDesc();
  1082.     if( g_bShowHelp )
  1083.     {
  1084.         txtHelper.SetInsertionPos( 10, pd3dsdBackBuffer->Height-15*12 );
  1085.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 0.75f, 0.0f, 1.0f ) );
  1086.         txtHelper.DrawTextLine( L"Controls:" );
  1087.  
  1088.         txtHelper.SetInsertionPos( 40, pd3dsdBackBuffer->Height-15*11 );
  1089.         txtHelper.DrawTextLine( L"Rotate object: Left drag mouse\n"
  1090.                                 L"Adjust camera: Right drag mouse\nZoom In/Out: Mouse wheel\n"
  1091.                                 L"Adjust reflectivity: E,D\nAdjust light intensity: W,S\n"
  1092.                                 L"Hide help: F1\n"
  1093.                                 L"Quit: ESC" );
  1094.     }
  1095.     else
  1096.     {
  1097.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 0.75f, 0.0f, 1.0f ) );
  1098.         txtHelper.DrawTextLine( L"Press F1 for help" );
  1099.     }
  1100.  
  1101.     txtHelper.SetForegroundColor( D3DXCOLOR( 0.0f, 1.0f, 0.0f, 1.0f ) );
  1102.     txtHelper.SetInsertionPos( 10, pd3dsdBackBuffer->Height - 48 );
  1103.     txtHelper.DrawTextLine( L"Cube map format\n"
  1104.                             L"Material reflectivity ( e/E, d/D )\n"
  1105.                             L"Light intensity ( w/W, s/S )\n" );
  1106.     txtHelper.SetInsertionPos( 190, pd3dsdBackBuffer->Height - 48 );
  1107.     txtHelper.DrawFormattedTextLine( L"%s\n%.2f\n%.1f",
  1108.                                      g_bUseFloatCubeMap ?
  1109.                                        L"Floating-point ( D3D9 / HDR )" :
  1110.                                        L"Integer ( D3D8 )",
  1111.                                      g_fReflectivity, g_vLightIntensity.x );
  1112.  
  1113.     txtHelper.End();
  1114. }
  1115.  
  1116.  
  1117. //--------------------------------------------------------------------------------------
  1118. // Before handling window messages, the sample framework passes incoming windows 
  1119. // messages to the application through this callback function. If the application sets 
  1120. // *pbNoFurtherProcessing to TRUE, then the sample framework will not process this message.
  1121. //--------------------------------------------------------------------------------------
  1122. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing )
  1123. {
  1124.     HRESULT hr;
  1125.  
  1126.     // Give the dialogs a chance to handle the message first
  1127.     *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
  1128.     if( *pbNoFurtherProcessing )
  1129.         return 0;
  1130.  
  1131.     // Pass all remaining windows messages to camera so it can respond to user input
  1132.     g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
  1133.  
  1134.     switch( uMsg )
  1135.     {
  1136.         //
  1137.         // Use WM_CHAR to handle parameter adjustment so
  1138.         // that we can control the granularity based on
  1139.         // the letter cases.
  1140.         case WM_CHAR:
  1141.         {
  1142.             switch( wParam )
  1143.             {
  1144.                 case 'W':
  1145.                 case 'w':
  1146.                     if( 'w' == wParam )
  1147.                         g_vLightIntensity += D3DXVECTOR4( 0.1f, 0.1f, 0.1f, 0.0f );
  1148.                     else
  1149.                         g_vLightIntensity += D3DXVECTOR4( 10.0f, 10.0f, 10.0f, 0.0f );
  1150.                     if( g_vLightIntensity.x > 150.0f )
  1151.                     {
  1152.                         g_vLightIntensity.x =
  1153.                         g_vLightIntensity.y =
  1154.                         g_vLightIntensity.z = 150.0f;
  1155.                     }
  1156.                     V( g_pEffect->SetVector( g_hLightIntensity, &g_vLightIntensity ) );
  1157.                     UpdateUiWithChanges();
  1158.                     break;
  1159.  
  1160.                 case 'S':
  1161.                 case 's':
  1162.                     if( 's' == wParam )
  1163.                         g_vLightIntensity -= D3DXVECTOR4( 0.1f, 0.1f, 0.1f, 0.0f );
  1164.                     else
  1165.                         g_vLightIntensity -= D3DXVECTOR4( 10.0f, 10.0f, 10.0f, 0.0f );
  1166.                     if( g_vLightIntensity.x < 0.0f )
  1167.                         g_vLightIntensity.x =
  1168.                         g_vLightIntensity.y =
  1169.                         g_vLightIntensity.z = 0.0f;
  1170.                     V( g_pEffect->SetVector( g_hLightIntensity, &g_vLightIntensity ) );
  1171.                     UpdateUiWithChanges();
  1172.                     break;
  1173.  
  1174.                 case 'D':
  1175.                 case 'd':
  1176.                     if( 'd' == wParam)
  1177.                         g_fReflectivity -= 0.01f;
  1178.                     else
  1179.                         g_fReflectivity -= 0.1f;
  1180.                     if( g_fReflectivity < 0 )
  1181.                         g_fReflectivity = 0;
  1182.                     V( g_pEffect->SetFloat( g_hReflectivity, g_fReflectivity ) );
  1183.                     UpdateUiWithChanges();
  1184.                     break;
  1185.  
  1186.                 case 'E':
  1187.                 case 'e':
  1188.                     if( 'e' == wParam )
  1189.                         g_fReflectivity += 0.01f;
  1190.                     else
  1191.                         g_fReflectivity += 0.1f;
  1192.                     if( g_fReflectivity > 1.0f )
  1193.                         g_fReflectivity = 1.0f;
  1194.                     V( g_pEffect->SetFloat( g_hReflectivity, g_fReflectivity ) );
  1195.                     UpdateUiWithChanges();
  1196.                     break;
  1197.             }
  1198.  
  1199.             return 0;
  1200.         }
  1201.     }
  1202.  
  1203.     return 0;
  1204. }
  1205.  
  1206.  
  1207. //--------------------------------------------------------------------------------------
  1208. // As a convenience, the sample framework inspects the incoming windows messages for
  1209. // keystroke messages and decodes the message parameters to pass relevant keyboard
  1210. // messages to the application.  The framework does not remove the underlying keystroke 
  1211. // messages, which are still passed to the application's MsgProc callback.
  1212. //--------------------------------------------------------------------------------------
  1213. void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown )
  1214. {
  1215.     if( bKeyDown )
  1216.     {
  1217.         switch( nChar )
  1218.         {
  1219.             case VK_F1: g_bShowHelp = !g_bShowHelp; break;
  1220.         }
  1221.     }
  1222. }
  1223.  
  1224.  
  1225. //--------------------------------------------------------------------------------------
  1226. // Handles the GUI events
  1227. //--------------------------------------------------------------------------------------
  1228. void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl )
  1229. {
  1230.     switch( nControlID )
  1231.     {
  1232.         case IDC_TOGGLEFULLSCREEN: DXUTToggleFullScreen(); break;
  1233.         case IDC_TOGGLEREF:        DXUTToggleREF(); break;
  1234.         case IDC_CHANGEDEVICE:     DXUTSetShowSettingsDialog( !DXUTGetShowSettingsDialog() ); break;
  1235.         case IDC_CHECKHDR:
  1236.             g_bUseFloatCubeMap = ((CDXUTCheckBox *)pControl)->GetChecked();
  1237.             if( g_bUseFloatCubeMap )
  1238.             {
  1239.                 g_nNumCubes = g_nNumFpCubeMap;
  1240.                 g_apCubeMap = g_apCubeMapFp;
  1241.                 g_pTech = g_aTechGroupFp;
  1242.             } else
  1243.             {
  1244.                 g_nNumCubes = 1;
  1245.                 g_apCubeMap = &g_pCubeMap32;
  1246.                 g_pTech = &g_TechGroup32;
  1247.             }
  1248.  
  1249.             break;
  1250.         case IDC_CHANGEMESH:
  1251.             if( ++g_nCurrMesh == NUM_MESHES )
  1252.                 g_nCurrMesh = 0;
  1253.             break;
  1254.  
  1255.         case IDC_RESETPARAM:
  1256.             ResetParameters();
  1257.             break;
  1258.  
  1259.         case IDC_SLIDERLIGHT:
  1260.             if( nEvent == EVENT_SLIDER_VALUE_CHANGED )
  1261.             {
  1262.                 CDXUTSlider *pSlider = (CDXUTSlider *)pControl;
  1263.                 g_vLightIntensity.x =
  1264.                 g_vLightIntensity.y =
  1265.                 g_vLightIntensity.z = pSlider->GetValue() * 0.1f;
  1266.                 if( g_pEffect )
  1267.                     g_pEffect->SetVector( g_hLightIntensity, &g_vLightIntensity );
  1268.                 CDXUTStatic *pStatic = g_HUD.GetStatic( IDC_SLIDERLIGHTTEXT );
  1269.                 if( pStatic )
  1270.                 {
  1271.                     WCHAR wszText[128];
  1272.                     swprintf( wszText, L"Light intensity: %0.2f", g_vLightIntensity.x );
  1273.                     pStatic->SetText( wszText );
  1274.                 }
  1275.             }
  1276.             break;
  1277.  
  1278.         case IDC_SLIDERREFLECT:
  1279.             if( nEvent == EVENT_SLIDER_VALUE_CHANGED )
  1280.             {
  1281.                 CDXUTSlider *pSlider = (CDXUTSlider *)pControl;
  1282.                 g_fReflectivity = pSlider->GetValue() * 0.01f;
  1283.                 if( g_pEffect )
  1284.                     g_pEffect->SetFloat( g_hReflectivity, g_fReflectivity );
  1285.                 UpdateUiWithChanges();
  1286.                 CDXUTStatic *pStatic = g_HUD.GetStatic( IDC_SLIDERREFLECTTEXT );
  1287.                 if( pStatic )
  1288.                 {
  1289.                     WCHAR wszText[128];
  1290.                     swprintf( wszText, L"Reflectivity: %0.2f", g_fReflectivity );
  1291.                     pStatic->SetText( wszText );
  1292.                 }
  1293.             }
  1294.             break;
  1295.     }
  1296. }
  1297.  
  1298.  
  1299. //--------------------------------------------------------------------------------------
  1300. // This callback function will be called immediately after the Direct3D device has 
  1301. // entered a lost state and before IDirect3DDevice9::Reset is called. Resources created
  1302. // in the OnResetDevice callback should be released here, which generally includes all 
  1303. // D3DPOOL_DEFAULT resources. See the "Lost Devices" section of the documentation for 
  1304. // information about lost devices.
  1305. //--------------------------------------------------------------------------------------
  1306. void CALLBACK OnLostDevice()
  1307. {
  1308.     if( g_pFont )
  1309.         g_pFont->OnLostDevice();
  1310.     if( g_pEffect )
  1311.         g_pEffect->OnLostDevice();
  1312.     SAFE_RELEASE(g_pTextSprite);
  1313.  
  1314.     for( int i = 0; i < NUM_MESHES; ++i )
  1315.         g_EnvMesh[i].m_Mesh.InvalidateDeviceObjects();
  1316.     g_Room.InvalidateDeviceObjects();
  1317.     g_LightMesh.InvalidateDeviceObjects();
  1318.     for( int i = 0; i < sizeof(g_Orbiter) / sizeof(g_Orbiter[0]); ++i )
  1319.         g_Orbiter[i].m_Mesh.InvalidateDeviceObjects();
  1320.  
  1321.     SAFE_RELEASE( g_apCubeMapFp[0] );
  1322.     SAFE_RELEASE( g_apCubeMapFp[1] );
  1323.     SAFE_RELEASE( g_pCubeMap32 );
  1324.     SAFE_RELEASE( g_pDepthCube );
  1325. }
  1326.  
  1327.  
  1328. //--------------------------------------------------------------------------------------
  1329. // This callback function will be called immediately after the Direct3D device has 
  1330. // been destroyed, which generally happens as a result of application termination or 
  1331. // windowed/full screen toggles. Resources created in the OnCreateDevice callback 
  1332. // should be released here, which generally includes all D3DPOOL_MANAGED resources. 
  1333. //--------------------------------------------------------------------------------------
  1334. void CALLBACK OnDestroyDevice()
  1335. {
  1336.     SAFE_RELEASE( g_pEffect );
  1337.     SAFE_RELEASE( g_pFont );
  1338.     SAFE_RELEASE( g_pVertDecl );
  1339.  
  1340.     g_Room.Destroy();
  1341.     g_LightMesh.Destroy();
  1342.     for( int i = 0; i < sizeof(g_Orbiter) / sizeof(g_Orbiter[0]); ++i )
  1343.         g_Orbiter[i].m_Mesh.Destroy();
  1344.     for( int i = 0; i < NUM_MESHES; ++i )
  1345.         g_EnvMesh[i].m_Mesh.Destroy();
  1346. }
  1347.